#include "DIFFE.h"

DIFFE_T* DIFFE_t;



//************************************
// Method:    	CALCU_SAMA						//< SAMA运算函数
// Programmer:  duan
// Time:		2019/03/17
// Returns:   	bool							//< 成功：true；失败：false
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	float dt						//< 运算周期
// Parameter: 	bool * DI						//< 数字量输入值数组指针
// Parameter: 	bool * DO						//< 数字量输出值数组指针
// Parameter: 	bool * AI						//< 模拟量输入值数组指针
// Parameter: 	bool * AO						//< 模拟量输出值数组指针
//************************************
bool CALCU_SAMA(DIFFE)(Model_Base_t* arg, float dt, bool* DI, bool* DO, float* AI, float* AO)
{
	/****************变量定义区开始**************/

	float a = 0;
	float Ud = 0;
	float Diffe = 0;
	/*<<<<<定义输入变量>>>>>*/
	float defAI;				

	/*<<<<<定义输出变量>>>>>*/
	float Output_Value;			

	/*<<<<<定义参数变量>>>>>*/
	float Init_Value;			//< 初始值
	float T;                    //< 时间常数 
	float K;                    //< 比例增益
	
	/*<<<<<定义中间变量>>>>>*/
	float* Mid_Value;
	float* LastAI;
	int* Cal_Flag;				//< 模块首次运算的标志
	float* LastUd;				//< duan0830 新增
	float* LastAO;				//< duan0830 新增

	/****************变量定义区结束**************/

	NAME(DIFFE)* Obj = (NAME(DIFFE)*)arg;

	/****************变量赋值**************/
	/*<<<<<输入变量赋值>>>>>*/
	defAI = AI[0];
	
	/*<<<<<参数变量赋值>>>>>*/
	Init_Value = Obj->Par.Init_Value;
	T = Obj->Par.T;
	K = Obj->Par.K;
	
	/*<<<<<中间变量赋值>>>>>*/
	Mid_Value = &(Obj->Sta.Mid_Value);
	LastAI = &(Obj->Sta.LastAI);
	Cal_Flag = &(Obj->Sta.Cal_Flag);
	LastUd = &(Obj->Sta.LastUd);
	LastAO = &(Obj->Sta.LastAO);
	/**************变量赋值结束************/

	/********************************************/
	/**************算法功能实现开始**************/
	/********************************************/
	
	if (T == 0)
		Output_Value = K / dt * (defAI - LastAI[0])  + Init_Value;			//< 只有一个S环节
	
	else
	{
		//< duan0830 按照该方法，算出的数值有些许误差
		//a = (float)exp(-dt / T);
		//Mid_Value[0] = a * Mid_Value[0] + K / T * (a -1 ) * defAI;			//< X[K+1] = a * X[k] + K/T * （a - 1）* u;    u 为输入
		//Output_Value = Mid_Value[0] + K / T * defAI;							//< y = X[K+1] + K / T * u;


		//< duan0830 新增
		Ud = (K*(defAI - LastAI[0]) + T * LastUd[0]) / (T + dt);
		Diffe = Ud - LastUd[0];
		Output_Value = LastAO[0] + Diffe;
	} 

	//if (Cal_Flag[0] == 0)														 //<不太理解其存在的意义
	//{
	//	Output_Value = Init_Value;
	//	Cal_Flag[0] = 1;
	//}

	LastAI[0] = defAI;
	LastUd[0] = Ud;
	LastAO[0] = Output_Value;
	/********************************************/
	/**************算法功能实现结束**************/
	/********************************************/	

	/****************运算结果输出**************/
	AO[0] = Output_Value;
	//< printf("微分模块的输出值为%f \r\n", AO[0]);       duan0827
	/**************运算结果输出完毕************/
	return true;
}



//************************************
// Method:    	BCPARA							//< 广播SAMA参数变量函数（无参数需要广播的模块直接将BCPara函数设置为NULL即可）
// Programmer:  duan
// Time:		2019/03/17
// Returns:   	int								//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 广播SAMA参数的数据包的指针
//************************************
int BC_PARA(DIFFE)(Model_Base_t* arg, void** Data)
{
	NAME(DIFFE)* Obj = (NAME(DIFFE)*)arg;
	BC_PARA_PUBLIC(Obj);
	return 0;
}



//************************************
// Method:    	BAK_STA							//< 备份SAMA运算中间参数
// Programmer:  duan
// Time:		2019/03/17
// Returns:   	int								//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 指定模块类型链表的指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int BAK_STA(DIFFE)(Model_Base_t* arg, void** Data)
{
	NAME(DIFFE)* Obj = (NAME(DIFFE)*)arg;
	BAK_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	ANA_STA							//< 解析备份的SAMA运算中间参数
// Programmer:  duan
// Time:		2019/03/17
// Returns:   	int								//< 成功：返回解析字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int ANA_STA(DIFFE)(Model_Base_t* arg, void** Data)
{
	NAME(DIFFE)* Obj = (NAME(DIFFE)*)arg;
	ANA_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	CHANGE_PAR				//< 在线修改模块参数函数
// Programmer:  duan
// Time:		2019/03/17
// Returns:   	int						//< 读取字节长度计数值
// Parameter: 	Model_Base_t* arg		//< 指定模块类型链表的指针
// Parameter: 	void** Data				//< 存放数据包当前指针位置的地址
//************************************
int CHANGE_PAR(DIFFE)(Model_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(DIFFE)*)arg)->Par, Data[0]);
	return _iLen;
}



//************************************
// Method:    	INIT_STAPAR						//< 初始化模块运算中间参数
// Programmer:  duan
// Time:		2019/03/17
// Parameter: 	Model_Base_t* arg				//< 模块参数结构体指针
//************************************
void INIT_STAPAR(DIFFE)(Model_Base_t* arg)
{
	NAME(DIFFE)* name = (NAME(DIFFE)*)arg;
	/****************初始化中间变量结构体**************/
	memset(&(name->Sta), 0, sizeof(name->Sta));
	/**************初始化中间变量结构体结束************/

	/****************对中间变量结构体的相关参数进行赋值**************/

	/**************对中间变量结构体的相关参数进行赋值结束************/
}
